package com.wangdao.wechatmall.config;

import com.wangdao.wechatmall.realm.AdminRealm;
import com.wangdao.wechatmall.realm.WXRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.LinkedHashMap;

/**
 * shiro相关配置
 *
 * @author ZhangXiao on 2021/7/9
 */
@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(securityManager);
//        shiroFilterFactoryBean.setUnauthorizedUrl("url");

//        shiroFilterFactoryBean.setLoginUrl("localhost:8080");

        LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();

        filterMap.put("/admin/auth/login","anon");
        filterMap.put("/wx/auth/login","anon");

        //filterMap.put("/**", "authc");



        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;
    }

    //shiro核心组件 SecurityManager
    @Bean
    public DefaultWebSecurityManager securityManager(AdminRealm adminRealm,
                                                     WXRealm wxRealm,
                                                     DefaultWebSessionManager webSessionManager,
                                                     CustomAuthenticator customAuthenticator,
                                                     CredentialsMatcher md5CredentialsMatcher) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //添加凭证密码
        adminRealm.setCredentialsMatcher(md5CredentialsMatcher);
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(wxRealm);
        wxRealm.setCredentialsMatcher(md5CredentialsMatcher);
        defaultWebSecurityManager.setRealms(realms);

        defaultWebSecurityManager.setSessionManager(webSessionManager);
        defaultWebSecurityManager.setAuthenticator(customAuthenticator);
        return defaultWebSecurityManager;


    }

    //声明式的注解--注解需要的权限
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    @Bean
    public DefaultWebSessionManager webSessionManager() {
        CustomSessionManager customSessionManager = new CustomSessionManager();
        return customSessionManager;
    }

    //将CustomAuthenticator中的方法重写后，再注册进来
    //需要在传入的参数中，告诉需要哪些realm，否则在CustomAuthenticator方法中的第一步中的realm为空
    @Bean
    public CustomAuthenticator customAuthenticator(AdminRealm adminRealm, WXRealm wxRealm) {
        CustomAuthenticator customAuthenticator = new CustomAuthenticator();
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(wxRealm);
        customAuthenticator.setRealms(realms);
        return customAuthenticator;
    }

    //获取MD5凭证匹配器
    @Bean
    public CredentialsMatcher md5CredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //使用MD5算法
        credentialsMatcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
        //迭代次数
        credentialsMatcher.setHashIterations(3);
        return credentialsMatcher;

    }
}
